package cz.edukomplex.kosilka.client.content.result;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

import com.fredhat.gwt.xmlrpc.client.XmlRpcClient;
import com.fredhat.gwt.xmlrpc.client.XmlRpcRequest;
import com.google.gwt.cell.client.EditTextCell;
import com.google.gwt.cell.client.FieldUpdater;
import com.google.gwt.cell.client.SelectionCell;
import com.google.gwt.cell.client.TextCell;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.cellview.client.CellList;
import com.google.gwt.user.cellview.client.CellTable;
import com.google.gwt.user.cellview.client.Column;
import com.google.gwt.user.cellview.client.HasKeyboardSelectionPolicy.KeyboardSelectionPolicy;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.SplitLayoutPanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.view.client.ProvidesKey;
import com.google.gwt.view.client.SelectionChangeEvent;
import com.google.gwt.view.client.SingleSelectionModel;

import cz.edukomplex.kosilka.client.helpers.MyXmlRpcClient;
import cz.edukomplex.kosilka.client.model.ResultSubjectModel;
import cz.edukomplex.kosilka.client.model.SubjectModel;

public class ResultContent extends Composite {

	interface ResultContentUiBinder extends UiBinder<Widget, ResultContent> {
	}

	private static ResultContentUiBinder uiBinder = GWT
			.create(ResultContentUiBinder.class);
	
				
	@UiField TextBox searchText;
	@UiField Button searchButton;
	@UiField(provided = true) CellList<ResultCellListRow> resultsCellList;
	@UiField SimplePanel cellTableWrapper;
	@UiField SplitLayoutPanel contentContainer;	
	@UiField ScrollPanel cellListScrollPanel;
	@UiField SimplePanel actionPanel;
	@UiField ScrollPanel scrollPanel;
	
	private ArrayList<ResultCellTableRow> resultsCellTableArrayList = new ArrayList<ResultCellTableRow>();
	private ArrayList<ResultCellListRow> resultsCellListArrayList = new ArrayList<ResultCellListRow>();	
	private SingleSelectionModel<ResultCellListRow> selectionModel = new SingleSelectionModel<ResultCellListRow>();
	private ArrayList<SubjectModel> subjectsArrayList = new ArrayList<SubjectModel>();
	private CellTable<ResultCellTableRow> resultsCellTable;
	private static final List<String> GRADES = Arrays.asList("Známka","A","B","C","D","E","F");	
	private static final ProvidesKey<ResultCellTableRow> KEY_PROVIDER = new ProvidesKey<ResultCellTableRow>() {

		@Override
		public Object getKey(ResultCellTableRow item) {
			return item.rid;
		}
	};
	
	
	
	public ResultContent() {
		resultsCellList = new CellList<ResultCellListRow>(new ResultCell());		
		initWidget(uiBinder.createAndBindUi(this));
		initCellList();
	}

	@UiHandler("searchButton")
	public void handleSearchButtonClick(ClickEvent e){
		Window.alert("Dokonci hladanie");
	}
	
	private void createTable() {
		
		
			/*
			 * Zoberie prveho studenta a podla toho zisti, do ktoreho oboru patri,
			 * potom na zaklade toho vyberie predmety
			 */
			String idStudenta = resultsCellTableArrayList.get(0).ID_st;
			XmlRpcClient client = MyXmlRpcClient.createClient();
			String methodName = "subject.fetchSubjectsByIDStudenta";
			Object[] params = new Object[]{idStudenta};
			
			XmlRpcRequest<ArrayList<HashMap<String, String>>> subjectRequest = new XmlRpcRequest<ArrayList<HashMap<String,String>>>(
					client, methodName, params, new AsyncCallback<ArrayList<HashMap<String, String>>>() {

						@Override
						public void onFailure(Throwable caught) {
							// TODO Auto-generated method stub
							
						}

						@Override
						public void onSuccess(
								ArrayList<HashMap<String, String>> result) {
							
							for (@SuppressWarnings("rawtypes")
							Iterator iterator = result.iterator(); iterator
									.hasNext();) {
								@SuppressWarnings("unchecked")
								HashMap<String, String> hashMap = (HashMap<String, String>) iterator
										.next();
																
								SubjectModel row = new SubjectModel(
										hashMap.get("sid"), 
										hashMap.get("name"),
										hashMap.get("short")
								);
								
								subjectsArrayList.add(row);
								
							}
							
							/*
							 * Ak trieda nema pridelen ziadne predmety tak nezobrazuj tabulku
							 */
							if(subjectsArrayList.size() == 0){
								Window.alert("Trieda nemá pridelené predmety");
								resultsCellTableArrayList.clear();
								refreshCellTable();
								resultsCellTable.setVisible(false);
								return;
							}
							
							resultsCellTable = new CellTable<ResultCellTableRow>(KEY_PROVIDER);
							
							Column<ResultCellTableRow, String> studentName = new Column<ResultCellTableRow, String>(new TextCell()) {
								
								@Override
								public String getValue(ResultCellTableRow object) {
									return object.lastName + " " + object.firstname;
								}
							};
							
							
							final Column<ResultCellTableRow, String> questionNumber = new Column<ResultCellTableRow, String>(new EditTextCell()) {
								
								@Override
								public String getValue(ResultCellTableRow object) {
									if(object.questionNumber == null){
										return "";
									}
									return object.questionNumber;
								}
							};
							questionNumber.setFieldUpdater(new FieldUpdater<ResultCellTableRow, String>() {
								
								@Override
								public void update(int index, ResultCellTableRow object, String value) {
									
									if(value.length() > 0){
										//je cislo?
										try{										
											Integer.parseInt(value);
										}catch(NumberFormatException e){
											/*
											 * Treba vymazat zadanu hodnotu z Cell
											 */
											EditTextCell questionCell = (EditTextCell)questionNumber.getCell();
											questionCell.clearViewData(KEY_PROVIDER.getKey(object));
											resultsCellTable.redraw();
											return;
										}
									}else {									
										value = "-1";//parameter -1 znamena, ze sa do db ma vlozit hodnota NULL
									}
									saveQuestionNumber(object,value);									
								}								
							});
							
							
							Column<ResultCellTableRow, String> oponentGrade = new Column<ResultCellTableRow, String>(new SelectionCell(GRADES)) {
								
								@Override
								public String getValue(ResultCellTableRow object) {
									return object.oponentGrade;
								}
							};
							oponentGrade.setFieldUpdater(new FieldUpdater<ResultCellTableRow, String>() {
								
								@Override
								public void update(int index, ResultCellTableRow object, String value) {
									saveGrade(
											Integer.valueOf(resultsCellTableArrayList.get(index).ID_st),
											object,
											value,
											"result.saveOponentGrade"
									);																
								}						
							});
							
							
							Column<ResultCellTableRow, String> veduciGrade = new Column<ResultCellTableRow, String>(new SelectionCell(GRADES)) {

								@Override
								public String getValue(ResultCellTableRow object) {
									return object.veduciGrade;
								}
							};
							veduciGrade.setFieldUpdater(new FieldUpdater<ResultCellTableRow, String>() {
								
								@Override
								public void update(int index, ResultCellTableRow object, String value) {
									saveGrade(
											Integer.valueOf(resultsCellTableArrayList.get(index).ID_st),
											object,
											value,
											"result.saveVeduciGrade"
									);																	
								}						
							});
							
							Column<ResultCellTableRow, String> obhajobaGrade = new Column<ResultCellTableRow, String>(new SelectionCell(GRADES)) {

								@Override
								public String getValue(ResultCellTableRow object) {
									return object.obhajobaGrade;
								}
							};
							obhajobaGrade.setFieldUpdater(new FieldUpdater<ResultCellTableRow, String>() {
								
								@Override
								public void update(int index, ResultCellTableRow object, String value) {
									saveGrade(
											Integer.valueOf(resultsCellTableArrayList.get(index).ID_st),
											object,
											value,
											"result.saveObhajobaGrade"
									);														
								}			
																
							});
							
							Column<ResultCellTableRow, String> overallGrade = new Column<ResultCellTableRow, String>(new SelectionCell(GRADES)) {

								@Override
								public String getValue(ResultCellTableRow object) {
									return object.overallGrade;
								}
							};
							overallGrade.setFieldUpdater(new FieldUpdater<ResultCellTableRow, String>() {
								
								@Override
								public void update(int index, ResultCellTableRow object, String value) {
									saveGrade(
											Integer.valueOf(resultsCellTableArrayList.get(index).ID_st),
											object,
											value,
											"result.saveOverallGrade"
									);																	
								}

																	
							});
							
							resultsCellTable.addColumn(studentName, "Meno študenta");
							resultsCellTable.addColumn(questionNumber,"Otázka");
							resultsCellTable.addColumn(oponentGrade,"Oponent");
							resultsCellTable.addColumn(veduciGrade,"Vedúci");
							resultsCellTable.addColumn(obhajobaGrade,"Obhajoba");
							resultsCellTable.addColumn(overallGrade,"Celkové hodnotenie");
							
																
							for (int i = 0; i < subjectsArrayList.size(); i++) {
								final int j = i;							
								Column<ResultCellTableRow, String> subjectColumn = new Column<ResultCellTableRow, String>(new SelectionCell(GRADES)) {
																				
									@Override
									public String getValue(ResultCellTableRow object) {
										/*
										 * Vrat hodnotenie, ak je pridelene; Inak v listobxe zobraz "Známka"  
										 */
										if(object.subjectsList.size() > 0){
											try{
												return object.subjectsList.get(j).grade;
											} catch(IndexOutOfBoundsException e){
												return GRADES.get(0);
											}
										}
										else {													
											return GRADES.get(0);
										}
									}
								};
								
								subjectColumn.setFieldUpdater(new FieldUpdater<ResultCellTableRow, String>() {
									
									@Override
									public void update(int index, ResultCellTableRow object, String value) {
										saveSubjectGrade(
												Integer.valueOf(resultsCellTableArrayList.get(index).ID_st),//ID_studenta
												Integer.valueOf(subjectsArrayList.get(j).sid),//sid
												object,//riadok tabulky
												value//vybrana znamka
										);																		
									}										
								});
								
								resultsCellTable.addColumn(subjectColumn, subjectsArrayList.get(i).shortName);
							}
						
							
							refreshCellTable();
						}						
					
			});
			
			subjectRequest.execute();
		
	}

	
	private void initCellList() {
		
		resultsCellList.setKeyboardSelectionPolicy(KeyboardSelectionPolicy.ENABLED);
		
		/*
		 * Nastavenie handler pri vybere
		 */
		selectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
			
			@Override
			public void onSelectionChange(SelectionChangeEvent event) {
				initCellTable();			
			}
		});
		resultsCellList.setSelectionModel(selectionModel);
		
		XmlRpcClient client = MyXmlRpcClient.createClient();
		String methodName = "harmonogram.fetchAll";
		
		XmlRpcRequest<ArrayList<HashMap<String, String>>> harmonogramRequest = 
			new XmlRpcRequest<ArrayList<HashMap<String,String>>>(
					client, methodName, null, new AsyncCallback<ArrayList<HashMap<String, String>>>() {

						@Override
						public void onFailure(Throwable caught) {
							// TODO Auto-generated method stub
							
						}

						@Override
						public void onSuccess(
								ArrayList<HashMap<String, String>> result) {
							parseCellListXMLResponse(result);							
						}
		});
		harmonogramRequest.execute();
		
	}

	private void initCellTable() {
			
		resultsCellTableArrayList.clear();
		subjectsArrayList.clear();
		scrollPanel.setVisible(true);
		
		XmlRpcClient client = MyXmlRpcClient.createClient();
		String methodName = "result.fetchResults";
		Object[] params = new Object[]{selectionModel.getSelectedObject().hid};
		XmlRpcRequest<ArrayList<HashMap<String, String>>> restultsRequest = new XmlRpcRequest<ArrayList<HashMap<String,String>>>(
				client, methodName, params, new AsyncCallback<ArrayList<HashMap<String, String>>>() {

					@Override
					public void onFailure(Throwable caught) {
						// TODO Auto-generated method stub
						
					}

					@Override
					public void onSuccess(
							ArrayList<HashMap<String, String>> result) {						
						parseCellTableXMLResponse(result);
						createTable();						
					}
		});
		restultsRequest.execute();		
	}
	
	private void parseCellListXMLResponse(ArrayList<HashMap<String, String>> result) {
		
		for (Iterator iterator = result.iterator(); iterator.hasNext();) {
			@SuppressWarnings("unchecked")
			HashMap<String, String> hashMap = (HashMap<String, String>) iterator
					.next();
			
			ResultCellListRow row = new ResultCellListRow(
					hashMap.get("hid"), 
					hashMap.get("harmonogram_name"), 
					hashMap.get("name")
			);
			
			resultsCellListArrayList.add(row);
			
		}
		
		refreshCellList();	
	}
	
	private void parseCellTableXMLResponse(ArrayList<HashMap<String, String>> result) {		
		
		for (@SuppressWarnings("rawtypes")
		Iterator iterator = result.iterator(); iterator.hasNext();) {
			
			
				@SuppressWarnings("unchecked")
				HashMap<String, String> hashMap = (HashMap<String, String>) iterator
				.next();
				
				ResultCellTableRow row = new ResultCellTableRow(
						hashMap.get("rid"), 
						hashMap.get("ID_st"), 
						hashMap.get("Jmeno"), 
						hashMap.get("Prijmeni"), 
						hashMap.get("oponent_grade"), 
						hashMap.get("veduci_grade"), 
						hashMap.get("obhajoba_grade"), 
						hashMap.get("overall_grade"), 
						hashMap.get("note"),
						hashMap.get("question_number"),
						null
				);
				
				resultsCellTableArrayList.add(row);
		}
			
		int i = 0;
		for (Iterator iterator2 = result.iterator(); iterator2.hasNext();) {
			
			@SuppressWarnings("unchecked")
			HashMap<String, ArrayList<HashMap<String, String>>> resultsHashMap = 
				(HashMap<String, ArrayList<HashMap<String, String>>>) iterator2.next();
			
			
			ArrayList<HashMap<String, String>> results = resultsHashMap.get("results");
			
			for (int j = 0; j < results.size(); j++) {
				ResultSubjectModel subjectRow = new ResultSubjectModel(
						results.get(j).get("sid"), 
						results.get(j).get("rid"),
						results.get(j).get("name"), 
						results.get(j).get("short"), 
						results.get(j).get("grade")
				);
				resultsCellTableArrayList.get(i).subjectsList.add(subjectRow);
			}		
			
			i++;			
		}		
	}
	
	
	private void refreshCellTable(){
		cellTableWrapper.setWidget(resultsCellTable);
		resultsCellTable.setWidth("100%");
		//nastavenie velkosti tabulky na velkost zaznamov
		resultsCellTable.setPageSize(resultsCellTableArrayList.size());
		//Nastavnie poctu riadkov
		resultsCellTable.setRowCount(resultsCellTableArrayList.size(), true);
	    // Obnovenie tabulky s novymi datami
		resultsCellTable.setRowData(0, resultsCellTableArrayList);		
	}	

	private void refreshCellList() {
		resultsCellList.setPageSize(resultsCellListArrayList.size());
		resultsCellList.setRowCount(resultsCellListArrayList.size(),true);
		resultsCellList.setRowData(0, resultsCellListArrayList);
		
		//Nastavenie vysky laveho panelu		
		int windowHeight = Window.getClientHeight();		
		int contentPosition = contentContainer.getAbsoluteTop();
		String height = (windowHeight - contentPosition) + "px";
		contentContainer.setHeight(height);
	}

	private void saveGrade(int idStudent,
			final ResultCellTableRow object, String value, String serviceMethodName) {
		
		
		XmlRpcClient client = MyXmlRpcClient.createClient();		
		Object[] params = new Object[]{idStudent,value};
		
		XmlRpcRequest<Integer> request = new XmlRpcRequest<Integer>(
				client, serviceMethodName, params, new AsyncCallback<Integer>() {

					@Override
					public void onFailure(Throwable caught) {
						// TODO Auto-generated method stub
						
					}

					@Override
					public void onSuccess(Integer result) {
						if(result > 0){
							object.setRid(String.valueOf(result));
						}						
					}
		});
		request.execute();
	}
	
	private void saveSubjectGrade(int idStudent,int sid,final ResultCellTableRow object, String value) {
		
		XmlRpcClient client = MyXmlRpcClient.createClient();		
		Object[] params = new Object[]{idStudent,object.rid,sid,value};
		String methodName = "result.saveSubjectGrade";
		
		XmlRpcRequest<Integer> request = new XmlRpcRequest<Integer>(
				client, methodName, params, new AsyncCallback<Integer>() {

					@Override
					public void onFailure(Throwable caught) {						
						Window.alert("Známku z predmetu sa nepodarilo uložiť");						
					}

					@Override
					public void onSuccess(Integer result) {
						
						if(result > 0){							
							object.setRid(String.valueOf(result));
						}else{
							Window.alert("Známku z predmetu sa nepodarilo uložiť");
						}
						
					}
		});
		request.execute();
	}
	
	private void saveQuestionNumber(final ResultCellTableRow object, final String value) {
				
		XmlRpcClient client = MyXmlRpcClient.createClient();
		String methodName = "result.setQuestionNumber";
		Object[] params = new Object[]{object.ID_st,value};
		
		XmlRpcRequest<Boolean> qnRequest = new XmlRpcRequest<Boolean>(
				client, methodName, params, new AsyncCallback<Boolean>() {

					@Override
					public void onFailure(Throwable caught) {
						// TODO Auto-generated method stub
						
					}

					@Override
					public void onSuccess(Boolean result) {
						if (result.equals(false)) {
							Window.alert("Číslo otázky sa nepodarilo uložiť");
						}		
						else {
							object.questionNumber = value;
						}
					}
		});
		qnRequest.execute();		
	}
}
